package com.pyl.admin.system.controller;

import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.pyl.admin.core.enums.ResultEnum;
import com.pyl.admin.core.exception.ResultException;
import com.pyl.admin.core.shiro.ShiroUtil;
import com.pyl.admin.core.utils.CaptchaUtil;
import com.pyl.admin.system.validator.LoginForm;
import com.pyl.core.config.properties.ProjectProperties;
import com.pyl.core.utils.ResultVoUtil;
import com.pyl.core.utils.SpringContextUtil;
import com.pyl.core.vo.ResultVo;
import com.pyl.core.wraps.URL;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 灵魂贰婶
 * @since 2019-06-28
 */
@Controller
public class SysLoginController implements ErrorController {

	/**
	 * 跳转到登录页面
	 */
	@GetMapping("/login")
	public String toLogin(Model model) {
		ProjectProperties properties = SpringContextUtil.getBean(ProjectProperties.class);
		model.addAttribute("isCaptcha", properties.isCaptchaOpen());
		return "/login";
	}

	/**
	 * 实现登录
	 * 
	 * @throws Exception
	 */
	@PostMapping("/login")
	@ResponseBody
	public ResultVo<?> login(@Validated LoginForm loginForm) {
		// 判断验证码是否正确
		ProjectProperties properties = SpringContextUtil.getBean(ProjectProperties.class);
		if (properties.isCaptchaOpen()) {
			Session session = SecurityUtils.getSubject().getSession();
			String code = (String) session.getAttribute("captcha");
			String captcha = loginForm.getCaptcha();
			if (StringUtils.isEmpty(captcha) || StringUtils.isEmpty(code)
					|| !captcha.toUpperCase().equals(code.toUpperCase())) {
				throw new ResultException(ResultEnum.USER_CAPTCHA_ERROR);
			}
			session.removeAttribute("captcha");
		}

		// 1.获取Subject主体对象
		Subject subject = SecurityUtils.getSubject();

		// 2.封装用户数据
		UsernamePasswordToken token = new UsernamePasswordToken(loginForm.getUsername(), loginForm.getPassword());

		// 3.执行登录，进入自定义Realm类中
		try {
			// 判断是否自动登录
			if (loginForm.getRememberMe() != null) {
				token.setRememberMe(true);
				ShiroUtil.RememberMe = true;
			} else {
				token.setRememberMe(false);
				ShiroUtil.RememberMe = false;
			}
			subject.login(token);
			return ResultVoUtil.success("登录成功", new URL("/"));
		} catch (AuthenticationException e) {
			return ResultVoUtil.error("用户名或密码错误");
		}
	}

	/**
	 * 验证码图片
	 */
	@GetMapping("/captcha")
	public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 设置响应头信息，通知浏览器不要缓存
		response.setHeader("Expires", "-1");
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "-1");
		response.setContentType("image/jpeg");

		// 获取验证码
		String code = CaptchaUtil.getRandomCode();
		// 将验证码输入到session中，用来验证
		request.getSession().setAttribute("captcha", code);
		// 输出到web页面
		ImageIO.write(CaptchaUtil.genCaptcha(code), "jpg", response.getOutputStream());
	}

	/**
	 * 退出登录
	 */
	@GetMapping("/logout")
	public String logout() {
		SecurityUtils.getSubject().logout();
		return "redirect:/login";
	}

	/**
	 * 权限不足页面
	 */
	@GetMapping("/noAuth")
	public String noAuth() {
		return "/system/main/no_auth";
	}

	/**
	 * 自定义错误页面
	 */
	@Override
	public String getErrorPath() {
		return "/error";
	}

	/**
	 * 处理错误页面
	 */
	@RequestMapping("/error")
	public String handleError(Model model, HttpServletRequest request) {
		Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
		String errorMsg = "好像出错了呢！";
		if (statusCode == 404) {
			errorMsg = "页面找不到了！好像是去火星了~";
		}

		model.addAttribute("statusCode", statusCode);
		model.addAttribute("msg", errorMsg);
		return "/system/main/error";
	}
}
